<h1 id="事件和信号">事件和信号</h1>
<h2 id="事件">事件</h2>
<blockquote>
<p>signals and slots 被其他人翻译成信号和槽机制，(⊙o⊙)…我这里还是不翻译好了。</p>
</blockquote>
<p>所有的应用都是事件驱动的。事件大部分都是由用户的行为产生的，当然也有其他的事件产生方式，比如网络的连接，窗口管理器或者定时器等。调用应用的exec_()方法时，应用会进入主循环，主循环会监听和分发事件。</p>
<p>在事件模型中，有三个角色：</p>
<ul>
<li>事件源</li>
<li>事件</li>
<li>事件目标</li>
</ul>
<p>事件源就是发生了状态改变的对象。事件是这个对象状态改变的内容。事件目标是事件想作用的目标。事件源绑定事件处理函数，然后作用于事件目标身上。</p>
<p>PyQt5处理事件方面有个signal and slot机制。Signals and slots用于对象间的通讯。事件触发的时候，发生一个signal，slot是用来被Python调用的（相当于一个句柄？这个词也好恶心，就是相当于事件的绑定函数）slot只有在事件触发的时候才能调用。</p>
<h2 id="signals-slots">Signals &amp; slots</h2>
<p>下面是signal &amp; slot的演示</p>
<div class="sourceCode" id="cb1"><pre><code class="language-python"><a class="sourceLine" id="cb1-1" data-line-number="1"><span class="co">#!/usr/bin/python3</span></a>
<a class="sourceLine" id="cb1-2" data-line-number="2"><span class="co"># -*- coding: utf-8 -*-</span></a>
<a class="sourceLine" id="cb1-3" data-line-number="3"></a>
<a class="sourceLine" id="cb1-4" data-line-number="4"><span class="co">&quot;&quot;&quot;</span></a>
<a class="sourceLine" id="cb1-5" data-line-number="5"><span class="co">ZetCode PyQt5 tutorial </span></a>
<a class="sourceLine" id="cb1-6" data-line-number="6"></a>
<a class="sourceLine" id="cb1-7" data-line-number="7"><span class="co">In this example, we connect a signal</span></a>
<a class="sourceLine" id="cb1-8" data-line-number="8"><span class="co">of a QSlider to a slot of a QLCDNumber. </span></a>
<a class="sourceLine" id="cb1-9" data-line-number="9"></a>
<a class="sourceLine" id="cb1-10" data-line-number="10"><span class="co">Author: Jan Bodnar</span></a>
<a class="sourceLine" id="cb1-11" data-line-number="11"><span class="co">Website: zetcode.com </span></a>
<a class="sourceLine" id="cb1-12" data-line-number="12"><span class="co">Last edited: January 2017</span></a>
<a class="sourceLine" id="cb1-13" data-line-number="13"><span class="co">&quot;&quot;&quot;</span></a>
<a class="sourceLine" id="cb1-14" data-line-number="14"></a>
<a class="sourceLine" id="cb1-15" data-line-number="15"><span class="im">import</span> sys</a>
<a class="sourceLine" id="cb1-16" data-line-number="16"><span class="im">from</span> PyQt5.QtCore <span class="im">import</span> Qt</a>
<a class="sourceLine" id="cb1-17" data-line-number="17"><span class="im">from</span> PyQt5.QtWidgets <span class="im">import</span> (QWidget, QLCDNumber, QSlider, </a>
<a class="sourceLine" id="cb1-18" data-line-number="18">    QVBoxLayout, QApplication)</a>
<a class="sourceLine" id="cb1-19" data-line-number="19"></a>
<a class="sourceLine" id="cb1-20" data-line-number="20"></a>
<a class="sourceLine" id="cb1-21" data-line-number="21"><span class="kw">class</span> Example(QWidget):</a>
<a class="sourceLine" id="cb1-22" data-line-number="22">    </a>
<a class="sourceLine" id="cb1-23" data-line-number="23">    <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>):</a>
<a class="sourceLine" id="cb1-24" data-line-number="24">        <span class="bu">super</span>().<span class="fu">__init__</span>()</a>
<a class="sourceLine" id="cb1-25" data-line-number="25">        </a>
<a class="sourceLine" id="cb1-26" data-line-number="26">        <span class="va">self</span>.initUI()</a>
<a class="sourceLine" id="cb1-27" data-line-number="27">        </a>
<a class="sourceLine" id="cb1-28" data-line-number="28">        </a>
<a class="sourceLine" id="cb1-29" data-line-number="29">    <span class="kw">def</span> initUI(<span class="va">self</span>):</a>
<a class="sourceLine" id="cb1-30" data-line-number="30">        </a>
<a class="sourceLine" id="cb1-31" data-line-number="31">        lcd <span class="op">=</span> QLCDNumber(<span class="va">self</span>)</a>
<a class="sourceLine" id="cb1-32" data-line-number="32">        sld <span class="op">=</span> QSlider(Qt.Horizontal, <span class="va">self</span>)</a>
<a class="sourceLine" id="cb1-33" data-line-number="33"></a>
<a class="sourceLine" id="cb1-34" data-line-number="34">        vbox <span class="op">=</span> QVBoxLayout()</a>
<a class="sourceLine" id="cb1-35" data-line-number="35">        vbox.addWidget(lcd)</a>
<a class="sourceLine" id="cb1-36" data-line-number="36">        vbox.addWidget(sld)</a>
<a class="sourceLine" id="cb1-37" data-line-number="37"></a>
<a class="sourceLine" id="cb1-38" data-line-number="38">        <span class="va">self</span>.setLayout(vbox)</a>
<a class="sourceLine" id="cb1-39" data-line-number="39">        sld.valueChanged.<span class="ex">connect</span>(lcd.display)</a>
<a class="sourceLine" id="cb1-40" data-line-number="40">        </a>
<a class="sourceLine" id="cb1-41" data-line-number="41">        <span class="va">self</span>.setGeometry(<span class="dv">300</span>, <span class="dv">300</span>, <span class="dv">250</span>, <span class="dv">150</span>)</a>
<a class="sourceLine" id="cb1-42" data-line-number="42">        <span class="va">self</span>.setWindowTitle(<span class="st">&#39;Signal and slot&#39;</span>)</a>
<a class="sourceLine" id="cb1-43" data-line-number="43">        <span class="va">self</span>.show()</a>
<a class="sourceLine" id="cb1-44" data-line-number="44">        </a>
<a class="sourceLine" id="cb1-45" data-line-number="45"></a>
<a class="sourceLine" id="cb1-46" data-line-number="46"><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&#39;__main__&#39;</span>:</a>
<a class="sourceLine" id="cb1-47" data-line-number="47">    </a>
<a class="sourceLine" id="cb1-48" data-line-number="48">    app <span class="op">=</span> QApplication(sys.argv)</a>
<a class="sourceLine" id="cb1-49" data-line-number="49">    ex <span class="op">=</span> Example()</a>
<a class="sourceLine" id="cb1-50" data-line-number="50">    sys.exit(app.exec_())</a></code></pre></div>
<p>上面的例子中，显示了<code>QtGui.QLCDNumber</code>和<code>QtGui.QSlider</code>模块，我们能拖动滑块让数字跟着发生改变。</p>
<pre><code class="language-python">sld.valueChanged.connect(lcd.display)</code></pre>
<p>这里是把滑块的变化和数字的变化绑定在一起。</p>
<p><code>sender</code>是信号的发送者，<code>receiver</code>是信号的接收者，<code>slot</code>是对这个信号应该做出的反应。</p>
<p>程序展示：</p>
<figure>
<img class="whitelist" src="docs/PyQt5/images/4-sigslot.png" alt="signal &amp; slot" />
</figure>
<h2 id="重构事件处理器">重构事件处理器</h2>
<p>在PyQt5中，事件处理器经常被重写（也就是用自己的覆盖库自带的）。</p>
<div class="sourceCode" id="cb3"><pre><code class="language-python"><a class="sourceLine" id="cb3-1" data-line-number="1"><span class="co">#!/usr/bin/python3</span></a>
<a class="sourceLine" id="cb3-2" data-line-number="2"><span class="co"># -*- coding: utf-8 -*-</span></a>
<a class="sourceLine" id="cb3-3" data-line-number="3"></a>
<a class="sourceLine" id="cb3-4" data-line-number="4"><span class="co">&quot;&quot;&quot;</span></a>
<a class="sourceLine" id="cb3-5" data-line-number="5"><span class="co">ZetCode PyQt5 tutorial </span></a>
<a class="sourceLine" id="cb3-6" data-line-number="6"></a>
<a class="sourceLine" id="cb3-7" data-line-number="7"><span class="co">In this example, we reimplement an </span></a>
<a class="sourceLine" id="cb3-8" data-line-number="8"><span class="co">event handler. </span></a>
<a class="sourceLine" id="cb3-9" data-line-number="9"></a>
<a class="sourceLine" id="cb3-10" data-line-number="10"><span class="co">Author: Jan Bodnar</span></a>
<a class="sourceLine" id="cb3-11" data-line-number="11"><span class="co">Website: zetcode.com </span></a>
<a class="sourceLine" id="cb3-12" data-line-number="12"><span class="co">Last edited: August 2017</span></a>
<a class="sourceLine" id="cb3-13" data-line-number="13"><span class="co">&quot;&quot;&quot;</span></a>
<a class="sourceLine" id="cb3-14" data-line-number="14"></a>
<a class="sourceLine" id="cb3-15" data-line-number="15"><span class="im">import</span> sys</a>
<a class="sourceLine" id="cb3-16" data-line-number="16"><span class="im">from</span> PyQt5.QtCore <span class="im">import</span> Qt</a>
<a class="sourceLine" id="cb3-17" data-line-number="17"><span class="im">from</span> PyQt5.QtWidgets <span class="im">import</span> QWidget, QApplication</a>
<a class="sourceLine" id="cb3-18" data-line-number="18"></a>
<a class="sourceLine" id="cb3-19" data-line-number="19"><span class="kw">class</span> Example(QWidget):</a>
<a class="sourceLine" id="cb3-20" data-line-number="20">    </a>
<a class="sourceLine" id="cb3-21" data-line-number="21">    <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>):</a>
<a class="sourceLine" id="cb3-22" data-line-number="22">        <span class="bu">super</span>().<span class="fu">__init__</span>()</a>
<a class="sourceLine" id="cb3-23" data-line-number="23">        </a>
<a class="sourceLine" id="cb3-24" data-line-number="24">        <span class="va">self</span>.initUI()</a>
<a class="sourceLine" id="cb3-25" data-line-number="25">        </a>
<a class="sourceLine" id="cb3-26" data-line-number="26">        </a>
<a class="sourceLine" id="cb3-27" data-line-number="27">    <span class="kw">def</span> initUI(<span class="va">self</span>):      </a>
<a class="sourceLine" id="cb3-28" data-line-number="28">        </a>
<a class="sourceLine" id="cb3-29" data-line-number="29">        <span class="va">self</span>.setGeometry(<span class="dv">300</span>, <span class="dv">300</span>, <span class="dv">250</span>, <span class="dv">150</span>)</a>
<a class="sourceLine" id="cb3-30" data-line-number="30">        <span class="va">self</span>.setWindowTitle(<span class="st">&#39;Event handler&#39;</span>)</a>
<a class="sourceLine" id="cb3-31" data-line-number="31">        <span class="va">self</span>.show()</a>
<a class="sourceLine" id="cb3-32" data-line-number="32">        </a>
<a class="sourceLine" id="cb3-33" data-line-number="33">        </a>
<a class="sourceLine" id="cb3-34" data-line-number="34">    <span class="kw">def</span> keyPressEvent(<span class="va">self</span>, e):</a>
<a class="sourceLine" id="cb3-35" data-line-number="35">        </a>
<a class="sourceLine" id="cb3-36" data-line-number="36">        <span class="cf">if</span> e.key() <span class="op">==</span> Qt.Key_Escape:</a>
<a class="sourceLine" id="cb3-37" data-line-number="37">            <span class="va">self</span>.close()</a>
<a class="sourceLine" id="cb3-38" data-line-number="38">        </a>
<a class="sourceLine" id="cb3-39" data-line-number="39">        </a>
<a class="sourceLine" id="cb3-40" data-line-number="40"><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&#39;__main__&#39;</span>:</a>
<a class="sourceLine" id="cb3-41" data-line-number="41">    </a>
<a class="sourceLine" id="cb3-42" data-line-number="42">    app <span class="op">=</span> QApplication(sys.argv)</a>
<a class="sourceLine" id="cb3-43" data-line-number="43">    ex <span class="op">=</span> Example()</a>
<a class="sourceLine" id="cb3-44" data-line-number="44">    sys.exit(app.exec_())</a></code></pre></div>
<p>这个例子中，我们替换了事件处理器函数<code>keyPressEvent()</code>。</p>
<pre><code class="language-python">def keyPressEvent(self, e):
    
    if e.key() == Qt.Key_Escape:
        self.close()</code></pre>
<p>此时如果按下ESC键程序就会退出。</p>
<p>程序展示：</p>
<p>这个就一个框，啥也没，就不展示了。</p>
<h2 id="事件对象">事件对象</h2>
<p>事件对象是用python来描述一系列的事件自身属性的对象。</p>
<div class="sourceCode" id="cb5"><pre><code class="language-python"><a class="sourceLine" id="cb5-1" data-line-number="1"><span class="co">#!/usr/bin/python3</span></a>
<a class="sourceLine" id="cb5-2" data-line-number="2"><span class="co"># -*- coding: utf-8 -*-</span></a>
<a class="sourceLine" id="cb5-3" data-line-number="3"></a>
<a class="sourceLine" id="cb5-4" data-line-number="4"><span class="co">&quot;&quot;&quot;</span></a>
<a class="sourceLine" id="cb5-5" data-line-number="5"><span class="co">ZetCode PyQt5 tutorial </span></a>
<a class="sourceLine" id="cb5-6" data-line-number="6"></a>
<a class="sourceLine" id="cb5-7" data-line-number="7"><span class="co">In this example, we display the x and y </span></a>
<a class="sourceLine" id="cb5-8" data-line-number="8"><span class="co">coordinates of a mouse pointer in a label widget.</span></a>
<a class="sourceLine" id="cb5-9" data-line-number="9"></a>
<a class="sourceLine" id="cb5-10" data-line-number="10"><span class="co">Author: Jan Bodnar</span></a>
<a class="sourceLine" id="cb5-11" data-line-number="11"><span class="co">Website: zetcode.com </span></a>
<a class="sourceLine" id="cb5-12" data-line-number="12"><span class="co">Last edited: August 2017</span></a>
<a class="sourceLine" id="cb5-13" data-line-number="13"><span class="co">&quot;&quot;&quot;</span></a>
<a class="sourceLine" id="cb5-14" data-line-number="14"></a>
<a class="sourceLine" id="cb5-15" data-line-number="15"><span class="im">import</span> sys</a>
<a class="sourceLine" id="cb5-16" data-line-number="16"><span class="im">from</span> PyQt5.QtCore <span class="im">import</span> Qt</a>
<a class="sourceLine" id="cb5-17" data-line-number="17"><span class="im">from</span> PyQt5.QtWidgets <span class="im">import</span> QWidget, QApplication, QGridLayout, QLabel</a>
<a class="sourceLine" id="cb5-18" data-line-number="18"></a>
<a class="sourceLine" id="cb5-19" data-line-number="19"><span class="kw">class</span> Example(QWidget):</a>
<a class="sourceLine" id="cb5-20" data-line-number="20">    </a>
<a class="sourceLine" id="cb5-21" data-line-number="21">    <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>):</a>
<a class="sourceLine" id="cb5-22" data-line-number="22">        <span class="bu">super</span>().<span class="fu">__init__</span>()</a>
<a class="sourceLine" id="cb5-23" data-line-number="23">        </a>
<a class="sourceLine" id="cb5-24" data-line-number="24">        <span class="va">self</span>.initUI()</a>
<a class="sourceLine" id="cb5-25" data-line-number="25">        </a>
<a class="sourceLine" id="cb5-26" data-line-number="26">        </a>
<a class="sourceLine" id="cb5-27" data-line-number="27">    <span class="kw">def</span> initUI(<span class="va">self</span>):      </a>
<a class="sourceLine" id="cb5-28" data-line-number="28">        </a>
<a class="sourceLine" id="cb5-29" data-line-number="29">        grid <span class="op">=</span> QGridLayout()</a>
<a class="sourceLine" id="cb5-30" data-line-number="30">        grid.setSpacing(<span class="dv">10</span>)</a>
<a class="sourceLine" id="cb5-31" data-line-number="31">        </a>
<a class="sourceLine" id="cb5-32" data-line-number="32">        x <span class="op">=</span> <span class="dv">0</span></a>
<a class="sourceLine" id="cb5-33" data-line-number="33">        y <span class="op">=</span> <span class="dv">0</span></a>
<a class="sourceLine" id="cb5-34" data-line-number="34">        </a>
<a class="sourceLine" id="cb5-35" data-line-number="35">        <span class="va">self</span>.text <span class="op">=</span> <span class="st">&quot;x: </span><span class="sc">{0}</span><span class="st">,  y: </span><span class="sc">{1}</span><span class="st">&quot;</span>.<span class="bu">format</span>(x, y)</a>
<a class="sourceLine" id="cb5-36" data-line-number="36">        </a>
<a class="sourceLine" id="cb5-37" data-line-number="37">        <span class="va">self</span>.label <span class="op">=</span> QLabel(<span class="va">self</span>.text, <span class="va">self</span>)</a>
<a class="sourceLine" id="cb5-38" data-line-number="38">        grid.addWidget(<span class="va">self</span>.label, <span class="dv">0</span>, <span class="dv">0</span>, Qt.AlignTop)</a>
<a class="sourceLine" id="cb5-39" data-line-number="39">        </a>
<a class="sourceLine" id="cb5-40" data-line-number="40">        <span class="va">self</span>.setMouseTracking(<span class="va">True</span>)</a>
<a class="sourceLine" id="cb5-41" data-line-number="41">        </a>
<a class="sourceLine" id="cb5-42" data-line-number="42">        <span class="va">self</span>.setLayout(grid)</a>
<a class="sourceLine" id="cb5-43" data-line-number="43">        </a>
<a class="sourceLine" id="cb5-44" data-line-number="44">        <span class="va">self</span>.setGeometry(<span class="dv">300</span>, <span class="dv">300</span>, <span class="dv">350</span>, <span class="dv">200</span>)</a>
<a class="sourceLine" id="cb5-45" data-line-number="45">        <span class="va">self</span>.setWindowTitle(<span class="st">&#39;Event object&#39;</span>)</a>
<a class="sourceLine" id="cb5-46" data-line-number="46">        <span class="va">self</span>.show()</a>
<a class="sourceLine" id="cb5-47" data-line-number="47">        </a>
<a class="sourceLine" id="cb5-48" data-line-number="48">        </a>
<a class="sourceLine" id="cb5-49" data-line-number="49">    <span class="kw">def</span> mouseMoveEvent(<span class="va">self</span>, e):</a>
<a class="sourceLine" id="cb5-50" data-line-number="50">        </a>
<a class="sourceLine" id="cb5-51" data-line-number="51">        x <span class="op">=</span> e.x()</a>
<a class="sourceLine" id="cb5-52" data-line-number="52">        y <span class="op">=</span> e.y()</a>
<a class="sourceLine" id="cb5-53" data-line-number="53">        </a>
<a class="sourceLine" id="cb5-54" data-line-number="54">        text <span class="op">=</span> <span class="st">&quot;x: </span><span class="sc">{0}</span><span class="st">,  y: </span><span class="sc">{1}</span><span class="st">&quot;</span>.<span class="bu">format</span>(x, y)</a>
<a class="sourceLine" id="cb5-55" data-line-number="55">        <span class="va">self</span>.label.setText(text)</a>
<a class="sourceLine" id="cb5-56" data-line-number="56">    </a>
<a class="sourceLine" id="cb5-57" data-line-number="57">        </a>
<a class="sourceLine" id="cb5-58" data-line-number="58"><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&#39;__main__&#39;</span>:</a>
<a class="sourceLine" id="cb5-59" data-line-number="59">    </a>
<a class="sourceLine" id="cb5-60" data-line-number="60">    app <span class="op">=</span> QApplication(sys.argv)</a>
<a class="sourceLine" id="cb5-61" data-line-number="61">    ex <span class="op">=</span> Example()</a>
<a class="sourceLine" id="cb5-62" data-line-number="62">    sys.exit(app.exec_())</a></code></pre></div>
<p>这个示例中，我们在一个组件里显示鼠标的X和Y坐标。</p>
<pre><code class="language-python">self.text = &quot;x: {0},  y: {1}&quot;.format(x, y)

self.label = QLabel(self.text, self)</code></pre>
<p>X Y坐标显示在<code>QLabel</code>组件里</p>
<pre><code class="language-python">self.setMouseTracking(True)</code></pre>
<p>事件追踪默认没有开启，当开启后才会追踪鼠标的点击事件。</p>
<pre><code class="language-python">def mouseMoveEvent(self, e):
    
    x = e.x()
    y = e.y()
    
    text = &quot;x: {0},  y: {1}&quot;.format(x, y)
    self.label.setText(text)</code></pre>
<p><code>e</code>代表了事件对象。里面有我们触发事件（鼠标移动）的事件对象。<code>x()</code>和<code>y()</code>方法得到鼠标的x和y坐标点，然后拼成字符串输出到<code>QLabel</code>组件里。</p>
<p>程序展示：</p>
<figure>
<img class="whitelist" src="docs/PyQt5/images/4-eventobject.png" alt="event object" />
</figure>
<h2 id="事件发送">事件发送</h2>
<p>有时候我们会想知道是哪个组件发出了一个信号，PyQt5里的<code>sender()</code>方法能搞定这件事。</p>
<div class="sourceCode" id="cb9"><pre><code class="language-python"><a class="sourceLine" id="cb9-1" data-line-number="1"><span class="co">#!/usr/bin/python3</span></a>
<a class="sourceLine" id="cb9-2" data-line-number="2"><span class="co"># -*- coding: utf-8 -*-</span></a>
<a class="sourceLine" id="cb9-3" data-line-number="3"></a>
<a class="sourceLine" id="cb9-4" data-line-number="4"><span class="co">&quot;&quot;&quot;</span></a>
<a class="sourceLine" id="cb9-5" data-line-number="5"><span class="co">ZetCode PyQt5 tutorial </span></a>
<a class="sourceLine" id="cb9-6" data-line-number="6"></a>
<a class="sourceLine" id="cb9-7" data-line-number="7"><span class="co">In this example, we determine the event sender</span></a>
<a class="sourceLine" id="cb9-8" data-line-number="8"><span class="co">object.</span></a>
<a class="sourceLine" id="cb9-9" data-line-number="9"></a>
<a class="sourceLine" id="cb9-10" data-line-number="10"><span class="co">Author: Jan Bodnar</span></a>
<a class="sourceLine" id="cb9-11" data-line-number="11"><span class="co">Website: zetcode.com </span></a>
<a class="sourceLine" id="cb9-12" data-line-number="12"><span class="co">Last edited: August 2017</span></a>
<a class="sourceLine" id="cb9-13" data-line-number="13"><span class="co">&quot;&quot;&quot;</span></a>
<a class="sourceLine" id="cb9-14" data-line-number="14"></a>
<a class="sourceLine" id="cb9-15" data-line-number="15"><span class="im">import</span> sys</a>
<a class="sourceLine" id="cb9-16" data-line-number="16"><span class="im">from</span> PyQt5.QtWidgets <span class="im">import</span> QMainWindow, QPushButton, QApplication</a>
<a class="sourceLine" id="cb9-17" data-line-number="17"></a>
<a class="sourceLine" id="cb9-18" data-line-number="18"></a>
<a class="sourceLine" id="cb9-19" data-line-number="19"><span class="kw">class</span> Example(QMainWindow):</a>
<a class="sourceLine" id="cb9-20" data-line-number="20">    </a>
<a class="sourceLine" id="cb9-21" data-line-number="21">    <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>):</a>
<a class="sourceLine" id="cb9-22" data-line-number="22">        <span class="bu">super</span>().<span class="fu">__init__</span>()</a>
<a class="sourceLine" id="cb9-23" data-line-number="23">        </a>
<a class="sourceLine" id="cb9-24" data-line-number="24">        <span class="va">self</span>.initUI()</a>
<a class="sourceLine" id="cb9-25" data-line-number="25">        </a>
<a class="sourceLine" id="cb9-26" data-line-number="26">        </a>
<a class="sourceLine" id="cb9-27" data-line-number="27">    <span class="kw">def</span> initUI(<span class="va">self</span>):      </a>
<a class="sourceLine" id="cb9-28" data-line-number="28"></a>
<a class="sourceLine" id="cb9-29" data-line-number="29">        btn1 <span class="op">=</span> QPushButton(<span class="st">&quot;Button 1&quot;</span>, <span class="va">self</span>)</a>
<a class="sourceLine" id="cb9-30" data-line-number="30">        btn1.move(<span class="dv">30</span>, <span class="dv">50</span>)</a>
<a class="sourceLine" id="cb9-31" data-line-number="31"></a>
<a class="sourceLine" id="cb9-32" data-line-number="32">        btn2 <span class="op">=</span> QPushButton(<span class="st">&quot;Button 2&quot;</span>, <span class="va">self</span>)</a>
<a class="sourceLine" id="cb9-33" data-line-number="33">        btn2.move(<span class="dv">150</span>, <span class="dv">50</span>)</a>
<a class="sourceLine" id="cb9-34" data-line-number="34">      </a>
<a class="sourceLine" id="cb9-35" data-line-number="35">        btn1.clicked.<span class="ex">connect</span>(<span class="va">self</span>.buttonClicked)            </a>
<a class="sourceLine" id="cb9-36" data-line-number="36">        btn2.clicked.<span class="ex">connect</span>(<span class="va">self</span>.buttonClicked)</a>
<a class="sourceLine" id="cb9-37" data-line-number="37">        </a>
<a class="sourceLine" id="cb9-38" data-line-number="38">        <span class="va">self</span>.statusBar()</a>
<a class="sourceLine" id="cb9-39" data-line-number="39">        </a>
<a class="sourceLine" id="cb9-40" data-line-number="40">        <span class="va">self</span>.setGeometry(<span class="dv">300</span>, <span class="dv">300</span>, <span class="dv">290</span>, <span class="dv">150</span>)</a>
<a class="sourceLine" id="cb9-41" data-line-number="41">        <span class="va">self</span>.setWindowTitle(<span class="st">&#39;Event sender&#39;</span>)</a>
<a class="sourceLine" id="cb9-42" data-line-number="42">        <span class="va">self</span>.show()</a>
<a class="sourceLine" id="cb9-43" data-line-number="43">        </a>
<a class="sourceLine" id="cb9-44" data-line-number="44">        </a>
<a class="sourceLine" id="cb9-45" data-line-number="45">    <span class="kw">def</span> buttonClicked(<span class="va">self</span>):</a>
<a class="sourceLine" id="cb9-46" data-line-number="46">      </a>
<a class="sourceLine" id="cb9-47" data-line-number="47">        sender <span class="op">=</span> <span class="va">self</span>.sender()</a>
<a class="sourceLine" id="cb9-48" data-line-number="48">        <span class="va">self</span>.statusBar().showMessage(sender.text() <span class="op">+</span> <span class="st">&#39; was pressed&#39;</span>)</a>
<a class="sourceLine" id="cb9-49" data-line-number="49">        </a>
<a class="sourceLine" id="cb9-50" data-line-number="50">        </a>
<a class="sourceLine" id="cb9-51" data-line-number="51"><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&#39;__main__&#39;</span>:</a>
<a class="sourceLine" id="cb9-52" data-line-number="52">    </a>
<a class="sourceLine" id="cb9-53" data-line-number="53">    app <span class="op">=</span> QApplication(sys.argv)</a>
<a class="sourceLine" id="cb9-54" data-line-number="54">    ex <span class="op">=</span> Example()</a>
<a class="sourceLine" id="cb9-55" data-line-number="55">    sys.exit(app.exec_())</a></code></pre></div>
<p>这个例子里有俩按钮，<code>buttonClicked()</code>方法决定了是哪个按钮能调用<code>sender()</code>方法。</p>
<pre><code class="language-python">btn1.clicked.connect(self.buttonClicked)            
btn2.clicked.connect(self.buttonClicked)</code></pre>
<p>两个按钮都和同一个slot绑定。</p>
<pre><code class="language-python">def buttonClicked(self):
  
    sender = self.sender()
    self.statusBar().showMessage(sender.text() + &#39; was pressed&#39;)</code></pre>
<p>我们用调用<code>sender()</code>方法的方式决定了事件源。状态栏显示了被点击的按钮。</p>
<p>程序展示：</p>
<figure>
<img class="whitelist" src="docs/PyQt5/images/4-eventsender.png" alt="event sender" />
</figure>
<h2 id="信号发送">信号发送</h2>
<p><code>QObject</code>实例能发送事件信号。下面的例子是发送自定义的信号。</p>
<div class="sourceCode" id="cb12"><pre><code class="language-python"><a class="sourceLine" id="cb12-1" data-line-number="1"><span class="co">#!/usr/bin/python3</span></a>
<a class="sourceLine" id="cb12-2" data-line-number="2"><span class="co"># -*- coding: utf-8 -*-</span></a>
<a class="sourceLine" id="cb12-3" data-line-number="3"></a>
<a class="sourceLine" id="cb12-4" data-line-number="4"><span class="co">&quot;&quot;&quot;</span></a>
<a class="sourceLine" id="cb12-5" data-line-number="5"><span class="co">ZetCode PyQt5 tutorial </span></a>
<a class="sourceLine" id="cb12-6" data-line-number="6"></a>
<a class="sourceLine" id="cb12-7" data-line-number="7"><span class="co">In this example, we show how to </span></a>
<a class="sourceLine" id="cb12-8" data-line-number="8"><span class="co">emit a custom signal. </span></a>
<a class="sourceLine" id="cb12-9" data-line-number="9"></a>
<a class="sourceLine" id="cb12-10" data-line-number="10"><span class="co">Author: Jan Bodnar</span></a>
<a class="sourceLine" id="cb12-11" data-line-number="11"><span class="co">Website: zetcode.com </span></a>
<a class="sourceLine" id="cb12-12" data-line-number="12"><span class="co">Last edited: August 2017</span></a>
<a class="sourceLine" id="cb12-13" data-line-number="13"><span class="co">&quot;&quot;&quot;</span></a>
<a class="sourceLine" id="cb12-14" data-line-number="14"></a>
<a class="sourceLine" id="cb12-15" data-line-number="15"><span class="im">import</span> sys</a>
<a class="sourceLine" id="cb12-16" data-line-number="16"><span class="im">from</span> PyQt5.QtCore <span class="im">import</span> pyqtSignal, QObject</a>
<a class="sourceLine" id="cb12-17" data-line-number="17"><span class="im">from</span> PyQt5.QtWidgets <span class="im">import</span> QMainWindow, QApplication</a>
<a class="sourceLine" id="cb12-18" data-line-number="18"></a>
<a class="sourceLine" id="cb12-19" data-line-number="19"></a>
<a class="sourceLine" id="cb12-20" data-line-number="20"><span class="kw">class</span> Communicate(QObject):</a>
<a class="sourceLine" id="cb12-21" data-line-number="21">    </a>
<a class="sourceLine" id="cb12-22" data-line-number="22">    closeApp <span class="op">=</span> pyqtSignal() </a>
<a class="sourceLine" id="cb12-23" data-line-number="23">    </a>
<a class="sourceLine" id="cb12-24" data-line-number="24"></a>
<a class="sourceLine" id="cb12-25" data-line-number="25"><span class="kw">class</span> Example(QMainWindow):</a>
<a class="sourceLine" id="cb12-26" data-line-number="26">    </a>
<a class="sourceLine" id="cb12-27" data-line-number="27">    <span class="kw">def</span> <span class="fu">__init__</span>(<span class="va">self</span>):</a>
<a class="sourceLine" id="cb12-28" data-line-number="28">        <span class="bu">super</span>().<span class="fu">__init__</span>()</a>
<a class="sourceLine" id="cb12-29" data-line-number="29">        </a>
<a class="sourceLine" id="cb12-30" data-line-number="30">        <span class="va">self</span>.initUI()</a>
<a class="sourceLine" id="cb12-31" data-line-number="31">        </a>
<a class="sourceLine" id="cb12-32" data-line-number="32">        </a>
<a class="sourceLine" id="cb12-33" data-line-number="33">    <span class="kw">def</span> initUI(<span class="va">self</span>):      </a>
<a class="sourceLine" id="cb12-34" data-line-number="34"></a>
<a class="sourceLine" id="cb12-35" data-line-number="35">        <span class="va">self</span>.c <span class="op">=</span> Communicate()</a>
<a class="sourceLine" id="cb12-36" data-line-number="36">        <span class="va">self</span>.c.closeApp.<span class="ex">connect</span>(<span class="va">self</span>.close)       </a>
<a class="sourceLine" id="cb12-37" data-line-number="37">        </a>
<a class="sourceLine" id="cb12-38" data-line-number="38">        <span class="va">self</span>.setGeometry(<span class="dv">300</span>, <span class="dv">300</span>, <span class="dv">290</span>, <span class="dv">150</span>)</a>
<a class="sourceLine" id="cb12-39" data-line-number="39">        <span class="va">self</span>.setWindowTitle(<span class="st">&#39;Emit signal&#39;</span>)</a>
<a class="sourceLine" id="cb12-40" data-line-number="40">        <span class="va">self</span>.show()</a>
<a class="sourceLine" id="cb12-41" data-line-number="41">        </a>
<a class="sourceLine" id="cb12-42" data-line-number="42">        </a>
<a class="sourceLine" id="cb12-43" data-line-number="43">    <span class="kw">def</span> mousePressEvent(<span class="va">self</span>, event):</a>
<a class="sourceLine" id="cb12-44" data-line-number="44">        </a>
<a class="sourceLine" id="cb12-45" data-line-number="45">        <span class="va">self</span>.c.closeApp.emit()</a>
<a class="sourceLine" id="cb12-46" data-line-number="46">        </a>
<a class="sourceLine" id="cb12-47" data-line-number="47">        </a>
<a class="sourceLine" id="cb12-48" data-line-number="48"><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&#39;__main__&#39;</span>:</a>
<a class="sourceLine" id="cb12-49" data-line-number="49">    </a>
<a class="sourceLine" id="cb12-50" data-line-number="50">    app <span class="op">=</span> QApplication(sys.argv)</a>
<a class="sourceLine" id="cb12-51" data-line-number="51">    ex <span class="op">=</span> Example()</a>
<a class="sourceLine" id="cb12-52" data-line-number="52">    sys.exit(app.exec_())</a></code></pre></div>
<p>我们创建了一个叫closeApp的信号，这个信号会在鼠标按下的时候触发，事件与<code>QMainWindow</code>绑定。</p>
<pre><code class="language-python">class Communicate(QObject):
    
    closeApp = pyqtSignal()</code></pre>
<p><code>Communicate</code>类创建了一个<code>pyqtSignal()</code>属性的信号。</p>
<pre><code class="language-python">self.c = Communicate()
self.c.closeApp.connect(self.close) </code></pre>
<p><code>closeApp</code>信号<code>QMainWindow</code>的<code>close()</code>方法绑定。</p>
<pre><code class="language-python">def mousePressEvent(self, event):
    
    self.c.closeApp.emit()</code></pre>
<p>点击窗口的时候，发送closeApp信号，程序终止。</p>
<p>程序展示：</p>
<p>这个也是啥也没。</p>
